jetcrab\vm\executor/traits.rs
1//! # VM Execution Traits
2//!
3//! Defines the core traits that provide the interface for VM execution components.
4//! These traits define the contract that implementations must fulfill for stack
5//! operations, heap management, variable management, and instruction execution.
6//!
7//! ## Core Traits
8//!
9//! - **StackOperations**: Defines stack manipulation operations
10//! - **HeapOperations**: Defines heap memory management operations
11//! - **VariableManager**: Defines variable storage and retrieval operations
12//! - **InstructionExecutor**: Defines the main execution interface
13//!
14//! ## Design Principles
15//!
16//! The traits follow these design principles:
17//!
18//! - **Generic Implementation**: Use trait bounds for flexibility
19//! - **Clear Contracts**: Each trait has a well-defined responsibility
20//! - **Error Handling**: All operations return Result types
21//! - **Performance**: Optimized for common operations
22//!
23//! ## Usage
24//!
25//! ```rust
26//! use jetcrab::vm::executor::traits::{StackOperations, HeapOperations, VariableManager};
27//!
28//! struct MyVM<S, H, V>
29//! where
30//! S: StackOperations,
31//! H: HeapOperations,
32//! V: VariableManager,
33//! {
34//! stack: S,
35//! heap: H,
36//! variables: V,
37//! }
38//! ```
39
40use crate::vm::bytecode::Bytecode;
41use crate::vm::handle::HeapHandleId;
42use crate::vm::types::{ArgIndex, ArraySize, LocalIndex};
43use crate::vm::value::Value;
44
45/// Defines operations for manipulating the VM's operand stack
46///
47/// This trait provides the interface for all stack operations including
48/// pushing, popping, and inspecting stack contents.
49pub trait StackOperations {
50 /// Pushes a value onto the top of the stack
51 ///
52 /// # Arguments
53 /// * `value` - The value to push onto the stack
54 fn push(&mut self, value: Value);
55
56 /// Pops a value from the top of the stack
57 ///
58 /// # Returns
59 /// * `Some(value)` if the stack is not empty
60 /// * `None` if the stack is empty
61 fn pop(&mut self) -> Option<Value>;
62
63 /// Peeks at the top value without removing it
64 ///
65 /// # Returns
66 /// * `Some(&value)` if the stack is not empty
67 /// * `None` if the stack is empty
68 fn peek(&self) -> Option<&Value>;
69
70 /// Clears all values from the stack
71 fn clear(&mut self);
72
73 /// Gets the current number of values on the stack
74 ///
75 /// # Returns
76 /// * The number of values currently on the stack
77 fn len(&self) -> usize;
78
79 /// Checks if the stack is empty
80 ///
81 /// # Returns
82 /// * `true` if the stack contains no values
83 /// * `false` if the stack contains at least one value
84 fn is_empty(&self) -> bool;
85
86 /// Gets a mutable reference to the underlying stack
87 ///
88 /// This allows direct access to the stack for advanced operations
89 /// that cannot be expressed through the trait interface.
90 ///
91 /// # Returns
92 /// * A mutable reference to the underlying stack
93 fn stack_mut(&mut self) -> &mut crate::vm::stack::Stack;
94
95 /// Gets the current size of the stack
96 ///
97 /// This is a convenience method that delegates to `len()`.
98 ///
99 /// # Returns
100 /// * The number of values currently on the stack
101 fn size(&self) -> usize {
102 self.len()
103 }
104}
105
106/// Defines operations for managing the VM's heap memory
107///
108/// This trait provides the interface for all heap operations including
109/// object allocation, property access, and memory management.
110pub trait HeapOperations {
111 /// Allocates a new object on the heap
112 ///
113 /// # Returns
114 /// * A handle to the newly allocated object
115 fn alloc_object(&mut self) -> HeapHandleId;
116
117 /// Allocates a new array on the heap
118 ///
119 /// # Returns
120 /// * A handle to the newly allocated array
121 fn alloc_array(&mut self) -> HeapHandleId;
122
123 /// Allocates a new function on the heap
124 ///
125 /// # Arguments
126 /// * `bytecode` - The function's bytecode
127 /// * `arg_count` - The number of arguments the function accepts
128 /// * `local_count` - The number of local variables the function uses
129 ///
130 /// # Returns
131 /// * A handle to the newly allocated function
132 fn alloc_function(
133 &mut self,
134 bytecode: Bytecode,
135 arg_count: ArgIndex,
136 local_count: LocalIndex,
137 ) -> HeapHandleId;
138
139 /// Gets a property value from an object
140 ///
141 /// # Arguments
142 /// * `handle` - The handle to the object
143 /// * `key` - The name of the property to retrieve
144 ///
145 /// # Returns
146 /// * `Some(&value)` if the property exists
147 /// * `None` if the property does not exist
148 fn get_object_property(&self, handle: HeapHandleId, key: &str) -> Option<&Value>;
149
150 /// Sets a property value on an object
151 ///
152 /// # Arguments
153 /// * `handle` - The handle to the object
154 /// * `key` - The name of the property to set
155 /// * `value` - The value to assign to the property
156 fn set_object_property(&mut self, handle: HeapHandleId, key: String, value: Value);
157
158 /// Sets an element in an array
159 ///
160 /// # Arguments
161 /// * `handle` - The handle to the array
162 /// * `index` - The index where to set the element
163 /// * `value` - The value to assign to the array element
164 fn set_array_element(&mut self, handle: HeapHandleId, index: ArraySize, value: Value);
165
166 /// Gets a reference to the underlying heap
167 ///
168 /// This allows direct access to the heap for advanced operations
169 /// that cannot be expressed through the trait interface.
170 ///
171 /// # Returns
172 /// * A reference to the underlying heap
173 fn get_heap(&self) -> &crate::vm::heap::Heap;
174
175 /// Gets an element from an array
176 ///
177 /// # Arguments
178 /// * `handle` - The handle to the array
179 /// * `index` - The index of the element to retrieve
180 ///
181 /// # Returns
182 /// * `Some(&value)` if the element exists at the given index
183 /// * `None` if the index is out of bounds
184 fn get_array_element(&self, _handle: HeapHandleId, _index: ArraySize) -> Option<&Value> {
185 None
186 }
187
188 /// Checks if an object has a specific property
189 ///
190 /// # Arguments
191 /// * `handle` - The handle to the object
192 /// * `key` - The name of the property to check
193 ///
194 /// # Returns
195 /// * `true` if the property exists
196 /// * `false` if the property does not exist
197 fn has_object_property(&self, handle: HeapHandleId, key: &str) -> bool {
198 self.get_object_property(handle, key).is_some()
199 }
200
201 /// Gets the length of an array
202 ///
203 /// # Arguments
204 /// * `handle` - The handle to the array
205 ///
206 /// # Returns
207 /// * The number of elements in the array
208 fn get_array_length(&self, _handle: HeapHandleId) -> usize {
209 0
210 }
211}
212
213/// Defines operations for managing VM variables
214///
215/// This trait provides the interface for all variable operations including
216/// local variables, global variables, and function arguments.
217pub trait VariableManager {
218 /// Gets a local variable by index
219 ///
220 /// # Arguments
221 /// * `idx` - The index of the local variable
222 ///
223 /// # Returns
224 /// * `Some(&value)` if the variable exists
225 /// * `None` if the variable does not exist
226 fn get_local(&self, idx: usize) -> Option<&Value>;
227
228 /// Sets a local variable by index
229 ///
230 /// # Arguments
231 /// * `idx` - The index of the local variable
232 /// * `value` - The value to assign to the variable
233 fn set_local(&mut self, idx: usize, value: Value);
234
235 /// Gets a global variable by index
236 ///
237 /// # Arguments
238 /// * `idx` - The index of the global variable
239 ///
240 /// # Returns
241 /// * `Some(&value)` if the variable exists
242 /// * `None` if the variable does not exist
243 fn get_global(&self, idx: usize) -> Option<&Value>;
244
245 /// Sets a global variable by index
246 ///
247 /// # Arguments
248 /// * `idx` - The index of the global variable
249 /// * `value` - The value to assign to the variable
250 fn set_global(&mut self, idx: usize, value: Value);
251
252 /// Gets a mutable reference to a local variable by index
253 ///
254 /// # Arguments
255 /// * `idx` - The index of the local variable
256 ///
257 /// # Returns
258 /// * `Some(&mut value)` if the variable exists
259 /// * `None` if the variable does not exist
260 fn get_local_mut(&mut self, idx: usize) -> Option<&mut Value>;
261
262 /// Gets a mutable reference to a global variable by index
263 ///
264 /// # Arguments
265 /// * `idx` - The index of the global variable
266 ///
267 /// # Returns
268 /// * `Some(&mut value)` if the variable exists
269 /// * `None` if the variable does not exist
270 fn get_global_mut(&mut self, idx: usize) -> Option<&mut Value>;
271
272 /// Gets a function argument by index
273 ///
274 /// This is a convenience method that delegates to `get_local()`.
275 ///
276 /// # Arguments
277 /// * `idx` - The index of the argument
278 ///
279 /// # Returns
280 /// * `Some(&value)` if the argument exists
281 /// * `None` if the argument does not exist
282 fn get_argument(&self, idx: usize) -> Option<&Value> {
283 self.get_local(idx)
284 }
285
286 /// Sets a function argument by index
287 ///
288 /// This is a convenience method that delegates to `set_local()`.
289 ///
290 /// # Arguments
291 /// * `idx` - The index of the argument
292 /// * `value` - The value to assign to the argument
293 fn set_argument(&mut self, idx: usize, value: Value) {
294 self.set_local(idx, value);
295 }
296}
297
298/// Defines the main interface for VM instruction execution
299///
300/// This trait provides the core execution interface that the VM uses
301/// to run bytecode programs.
302pub trait InstructionExecutor {
303 /// Executes a bytecode program
304 ///
305 /// # Arguments
306 /// * `bytecode` - The bytecode to execute
307 /// * `constants` - The constant pool for the bytecode
308 ///
309 /// # Returns
310 /// * `Ok(())` on successful execution
311 /// * `Err(ExecutionError)` if execution fails
312 fn execute(
313 &mut self,
314 bytecode: &Bytecode,
315 constants: &[Value],
316 ) -> Result<(), crate::vm::executor::error_handler::ExecutionError>;
317}